/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit;

import picounit.features.aggregate_exception.Thrower;
import picounit.features.verify.CombinedConstraints;
import picounit.features.verify.DefaultVerify;
import picounit.features.verify.Evaluator;
import picounit.features.verify.IsTrue;
import picounit.features.verify.constraint.Stringer;
import picounit.verify.ReasonCapturer;
import previous.picounit.Is;
import junit.framework.AssertionFailedError;

public class VerifyTest implements previous.picounit.Test {
	private Verify verify;
	
	private final previous.picounit.Should should;
	private final Evaluator evaluator;

	private final Thrower thrower;

	interface Collaborators {
		Evaluator evaluator();
		Thrower thrower();
	}

	public VerifyTest(previous.picounit.Should should, Evaluator mockEvaluator, Thrower mockThrower) {
		this.should = should;
		this.evaluator = mockEvaluator;
		this.thrower = mockThrower;
		
		this.verify = new DefaultVerify(mockEvaluator, mockThrower, new CombinedConstraints(evaluator));
	}

	public void testFail(Is is) {
		thrower.errorEvent(is.instanceOf(AssertionFailedError.class));

		should.expectAboveWhenTheFollowingOccurs();

		verify.fail();
	}
	
	public void testFailWithMessage() {
		thrower.errorEvent(new AssertionFailedError() {
			@Override
			public boolean equals(Object object) {
				return object != null && (object instanceof AssertionFailedError) &&
					((AssertionFailedError) object).hasMessage("message");
			}
		});

		should.expectAboveWhenTheFollowingOccurs();

 		verify.fail("message");
	}
	
	public void testThat(Is is) {
		ReasonCapturer reasonCapturer = null;
		evaluator.setValue(true);

		IsTrue isTrue = is.instanceOf(IsTrue.class);
		Stringer isStringer = is.instanceOf(Stringer.class);
		ReasonCapturer evaluate = evaluator.evaluate(isTrue, isStringer);
		
		should.call(evaluate)
			.andReturn(reasonCapturer);

		should.expectAboveWhenTheFollowingOccurs();

		verify.that(true).isTrue();
	}

	public void testThatWithMessage(Is is) {
		evaluator.setReason("message");
		evaluator.setValue(true);

		IsTrue isTrue = is.instanceOf(IsTrue.class);
		Stringer isStringer = is.instanceOf(Stringer.class);
		ReasonCapturer evaluate = evaluator.evaluate(isTrue, isStringer);
		
		should.call(evaluate)
			.andReturn((ReasonCapturer) null);

		should.expectAboveWhenTheFollowingOccurs();

		verify.because("message").that(true).isTrue();
	}
}
